﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Text;

namespace JWFW.BOL
{
    /// <summary>
    /// 配置型对象基类，包含code属性的对象的基类
    /// 用于系统固定配置对象，如学校的课程列表
    /// 或含上述属性的非海量数据的记录型对象，如公司的项目、合同列表等
    /// 
    /// 当对象不含有code列时，可以在构造函数中设置m_hasCode为false，
    /// 此时本类相当于BaseEntity，但当调用使用code及codeField的方法时会出错【TODO：主动抛出异常信息】，
    /// 目的是使其他派生的基类可以满足有无code情况下都只需从本类继承
    /// </summary>
    [Serializable]
    public class BaseConfigEntity : BaseEntity
    {
        public BaseConfigEntity()
        {

        }

        #region 变量

        /// <summary>
        /// 表示代号字段，可在实体派生类的构造函数中赋值，对应到具体的数据库表
        /// </summary>
        protected string m_codeField = "code";

        /// <summary>
        /// 是否含有code列，可在实体派生类的构造函数中赋值
        /// </summary>
        protected bool m_hasCode = false;

        #region 简单成员变量

        /// <summary>
        /// 代号字段值
        /// </summary>
        protected string m_code = "";

        #endregion

        #endregion

        #region 属性

        /// <summary>
        /// 获取或设置代号code【唯一】
        /// </summary>
        public string Code
        {
            get
            {
                if (!m_hasCode)
                {
                    throw new BaseCustomException(LanguageResource.GetInfo(LanguageResource.EX_BOL_CodeNotAllowedErr, Language, this.GetType().ToString()));
                }
                return this.m_code;
            }
            set
            {
                if (!m_hasCode)
                {
                    throw new BaseCustomException(LanguageResource.GetInfo(LanguageResource.EX_BOL_CodeNotAllowedErr, Language, this.GetType().ToString()));
                }
                this.m_code = value;
            }
        }

        #endregion

        #region 方法

        #region 重载方法

        protected override void FillContainer()
        {
            base.FillContainer();
            if (this.m_hasCode)
            {
                this.m_container.Add(this.m_codeField, this.m_code);
            }
        }
        public override bool GetProperties(DataRow record)
        {
            if (!base.GetProperties(record))
            {
                return false;
            }
            if (this.m_hasCode)
            {
                this.m_code = this.GetStringValue(record, this.m_codeField);
            }
            return true;
        }
        public override void Init()
        {
            if (!m_hasCode)
            {
                base.Init();
            }
            else
            {
                this.GetProperties(m_code);
            }
        }
        public override int Add(bool blob = false, string transID = null)
        {
            lock (this.GetType())
            {
                if (m_hasCode)
                {
                    //没有输入code值
                    if (m_code.Trim() == "")
                    {
                        throw new BaseCustomException(LanguageResource.GetInfo(LanguageResource.EX_BOL_CodeIsEmptyErr, Language, this.GetType().ToString()));
                    }
                    //code值在数据库中已存在
                    if (!this.CanUpdate(transID))
                    {
                        throw new BaseCustomException(LanguageResource.GetInfo(LanguageResource.EX_BOL_CodeExistErr, Language, this.GetType().ToString()));
                    }
                }
                return base.Add(blob, transID);
            }
        }
        /// <summary>
        /// 根据code，将实例成员值更新到数据库，用于事务中
        /// </summary>
        /// <param name="blob">是否使用参数式，默认为false</param>
        /// <param name="removeAllObjectCache">是否移除当前类型的所有对象缓存</param>
        /// <param name="transID">事务ID，默认为null</param>
        public override int Update(bool blob = false, bool removeAllObjectCache = false, string transID = null)
        {
            lock (this.GetType())
            {
                if (m_hasCode)
                {
                    //没有输入code值
                    if (this.m_code.Trim() == "")
                    {
                        throw new BaseCustomException(LanguageResource.GetInfo(LanguageResource.EX_BOL_CodeIsEmptyErr, Language, this.GetType().ToString()));
                    }
                    //更新后的code值在数据库中已存在
                    if (!this.CanUpdate(transID))
                    {
                        throw new BaseCustomException(LanguageResource.GetInfo(LanguageResource.EX_BOL_CodeExistErr, Language, this.GetType().ToString()));
                    }
                }
                return base.Update(blob, removeAllObjectCache, transID);
            }
        }

        #endregion

        #region 内部辅助方法

        /// <summary>
        /// 获得以code为条件的sql条件语句，
        /// </summary>
        /// <returns></returns>
        protected string GetCodeConditionExpression(string code)
        {
            if (!m_hasCode)
            {
                throw new BaseCustomException(LanguageResource.GetInfo(LanguageResource.EX_BOL_CodeNotAllowedErr, Language, this.GetType().ToString()));
            }
            string condition = string.Format(" WHERE {0}={1}", DB.GetCol(m_codeField), DB.GetVal(code));
            return condition;
        }

        #endregion

        #region 公共方法

        /// <summary>
        /// 由指定的code获得本实例的成员属性值，用于事务中
        /// </summary>        
        /// <param name="transID">事务id，若在非事务中使用，则设置为null</param>
        /// <param name="code">code列值</param>
        /// <returns></returns>
        public void GetProperties(string code, string transID = null)
        {
            this.GetProperties(this.GetRecordByCode(code, transID));
        }
        /// <summary>
        /// 根据code，判断本实例是否可以进行记录更新
        /// 当code不可用时，始终返回true
        /// </summary>
        /// <param name="transID">事务id，若在非事务中使用，则设置为null</param>
        /// <returns></returns>
        public bool CanUpdate(string transID = null)
        {
            string condition = string.Format(
                "WHERE {0}={1} AND {2}<>{3}"
                , DB.GetCol(m_codeField), DB.GetVal(m_code)
                , DB.GetCol(m_idField), DB.GetVal(m_id));

            if (m_hasCode)
            {
                return !this.Exist(condition, false, transID);
            }
            else
            {
                return true;
            }
        }

        #endregion

        #region 全局方法

        /// <summary>
        /// 判断是否存在指定的简单条件的记录，用于事务中
        /// </summary>
        /// <param name="transID">事务id，若在非事务中使用，则设置为null</param>
        /// <param name="code">code列值</param>
        /// <returns></returns>
        public bool ExistByCode(string code, string transID = null)
        {
            string condition = this.GetCodeConditionExpression(code);
            return this.Exist(condition, true, transID);
        }
        /// <summary>
        /// 由指定的code获得一行记录，没有则返回null，用于事务中
        /// </summary>
        /// <param name="transID">事务id，若在非事务中使用，则设置为null</param>
        /// <param name="code">code列值</param>
        /// <returns></returns>
        public DataRow GetRecordByCode(string code, string transID = null)
        {
            if ((transID == null || transID.Trim() == "") && m_tblCacheManager.IsEnable)
            {
                DataTable dt = this.GetCacheTable();
                DataRow[] drs = dt.Select(DB.GetSimpleCondition(this.GetCodeConditionExpression(code)));
                if (drs.Length > 0)
                {
                    return drs[0];
                }
            }
            else
            {
                DataTable dt = this.GetRecords(this.GetCodeConditionExpression(code), transID);
                if (dt.Rows.Count > 0)
                {
                    DataRow dr = dt.Rows[0];
                    return dr;
                }
            }
            return null;
        }

        #endregion

        #endregion

    }
}
